# 文件创建时间: 2025-09-25
# 文件功能描述: 配置管理模块，负责读取和管理JSON配置文件中的参数设置

import json
import os
import logging
from typing import Dict, Any, Optional

class ConfigManager:
    """配置管理器，负责读取和管理JSON配置文件"""
    
    def __init__(self, config_path: Optional[str] = None):
        """初始化配置管理器
        
        Args:
            config_path: 配置文件路径，如果未提供则使用默认路径
        """
        if config_path is None:
            # 默认配置文件路径
            current_dir = os.path.dirname(os.path.abspath(__file__))
            config_path = os.path.join(os.path.dirname(current_dir), 'config', 'config.json')
        
        self.config_path = config_path
        self.config = {}
        self._load_config()
        
    def _load_config(self):
        """加载配置文件"""
        try:
            if not os.path.exists(self.config_path):
                logging.error(f"配置文件不存在: {self.config_path}")
                self._create_default_config()
                return
                
            with open(self.config_path, 'r', encoding='utf-8') as f:
                self.config = json.load(f)
            
            logging.info(f"成功加载配置文件: {self.config_path}")
            self._validate_config()
            
        except json.JSONDecodeError as e:
            logging.error(f"配置文件JSON格式错误: {e}")
            self._create_default_config()
        except Exception as e:
            logging.error(f"加载配置文件失败: {e}")
            self._create_default_config()
    
    def _validate_config(self):
        """验证配置文件的完整性"""
        required_sections = ['grid', 'time_settings', 'solver', 'inlet_conditions', 
                           'outlet_conditions', 'physical_parameters', 'boundary_conditions']
        
        for section in required_sections:
            if section not in self.config:
                logging.warning(f"配置文件缺少必需的节: {section}")
                
        # 验证关键参数的有效性
        if 'grid' in self.config:
            grid_config = self.config['grid']
            if grid_config.get('n_axial', 0) <= 0:
                logging.warning("网格轴向节点数必须大于0")
            if grid_config.get('channel_length', 0) <= 0:
                logging.warning("通道长度必须大于0")
                
        if 'inlet_conditions' in self.config:
            inlet_config = self.config['inlet_conditions']
            if inlet_config.get('pressure', 0) <= 0:
                logging.warning("入口压力必须大于0")
            if not 0 <= inlet_config.get('alpha', 0) <= 1:
                logging.warning("入口空泡份额必须在0-1之间")
    
    def _create_default_config(self):
        """创建默认配置"""
        self.config = {
            "grid": {
                "n_axial": 10,
                "channel_length": 1.0,
                "channel_width": 0.0127
            },
            "geometry": {
                "rod_diameter": 0.01,
                "rod_pitch": 0.013
            },
            "time_settings": {
                "total_time": 10.0,
                "initial_dt": 1e-4,
                "min_dt": 1e-6,
                "max_dt": 0.01
            },
            "solver": {
                "max_iterations_per_step": 200,
                "convergence_criteria": {
                    "pressure": 1e-1,
                    "velocity": 1e-1,
                    "void_fraction": 1e-1
                },
                "relaxation_factors": {
                    "pressure": 0.001,
                    "velocity": 0.05,
                    "void_fraction": 0.01
                }
            },
            "inlet_conditions": {
                "pressure": 1.1e5,
                "temperature": 298.15,
                "alpha": 0.05,
                "liquid": {
                    "velocity": 0.08
                },
                "vapor": {
                    "velocity": 0.1
                }
            },
            "outlet_conditions": {
                "pressure": 1.08e5
            },
            "physical_parameters": {
                "gravity": 9.81,
                "turbulent_mixing_coefficient": 0.005,
                "interfacial_friction_coefficient": 0.5,
                "lateral_flow_resistance": 0.5,
                "fluid_properties": {
                    "temperature": 298.15,
                    "liquid_density": 997.0,
                    "liquid_viscosity": 8.9e-4,
                    "vapor_density": 1.225,
                    "vapor_viscosity": 1.81e-5
                }
            }
        }
        
        logging.info("使用默认配置")
    
    def get(self, key_path: str, default: Any = None) -> Any:
        """获取配置值
        
        Args:
            key_path: 配置键路径，支持点分隔符，如 'grid.n_axial'
            default: 默认值
            
        Returns:
            配置值
        """
        keys = key_path.split('.')
        value = self.config
        
        try:
            for key in keys:
                value = value[key]
            return value
        except (KeyError, TypeError):
            logging.warning(f"配置键不存在: {key_path}，使用默认值: {default}")
            return default
    
    def set(self, key_path: str, value: Any) -> None:
        """设置配置值
        
        Args:
            key_path: 配置键路径
            value: 配置值
        """
        keys = key_path.split('.')
        config = self.config
        
        # 创建嵌套字典结构
        for key in keys[:-1]:
            if key not in config:
                config[key] = {}
            config = config[key]
        
        config[keys[-1]] = value
    
    def save_config(self, config_path: Optional[str] = None) -> bool:
        """保存配置到文件
        
        Args:
            config_path: 保存路径，如果未提供则使用原路径
            
        Returns:
            是否保存成功
        """
        if config_path is None:
            config_path = self.config_path
            
        try:
            # 确保目录存在
            os.makedirs(os.path.dirname(config_path), exist_ok=True)
            
            with open(config_path, 'w', encoding='utf-8') as f:
                json.dump(self.config, f, indent=4, ensure_ascii=False)
            
            logging.info(f"配置已保存到: {config_path}")
            return True
            
        except Exception as e:
            logging.error(f"保存配置文件失败: {e}")
            return False
    
    def get_grid_config(self) -> Dict[str, Any]:
        """获取网格配置"""
        return {
            'n_axial': self.get('grid.n_axial', 10),
            'channel_length': self.get('grid.channel_length', 1.0),
            'channel_width': self.get('grid.channel_width', 0.0127)
        }
    
    def get_geometry_config(self) -> Dict[str, Any]:
        """获取几何配置"""
        return {
            'rod_diameter': self.get('geometry.rod_diameter', 0.01),
            'rod_pitch': self.get('geometry.rod_pitch', 0.013)
        }
    
    def get_solver_config(self) -> Dict[str, Any]:
        """获取求解器配置
        
        【修改2025-11-05】支持分离的气液相速度松弛因子
        - velocity_g: 气相速度松弛因子
        - velocity_l: 液相速度松弛因子
        - velocity: 统一速度松弛因子（向后兼容）
        """
        # 读取分离的气液相松弛因子，如果不存在则使用统一的velocity值
        velocity_unified = self.get('solver.relaxation_factors.velocity', None)
        velocity_g = self.get('solver.relaxation_factors.velocity_g', velocity_unified if velocity_unified else 0.2)
        velocity_l = self.get('solver.relaxation_factors.velocity_l', velocity_unified if velocity_unified else 0.4)
        
        return {
            'max_iterations': self.get('solver.max_iterations_per_step', 300),
            'convergence_tolerance': max(
                self.get('solver.convergence_criteria.pressure', 1e-2),
                self.get('solver.convergence_criteria.velocity', 5e-3),
                self.get('solver.convergence_criteria.void_fraction', 1e-4)
            ),
            'relaxation_factors': {
                'pressure': self.get('solver.relaxation_factors.pressure', 0.1),
                'velocity_g': velocity_g,
                'velocity_l': velocity_l,
                'void_fraction': self.get('solver.relaxation_factors.void_fraction', 0.02)
            }
        }
    
    def get_inlet_conditions(self) -> Dict[str, Any]:
        """获取入口条件"""
        return {
            'pressure': self.get('inlet_conditions.pressure', 1.1e5),
            'temperature': self.get('inlet_conditions.temperature', 298.15),
            'alpha': self.get('inlet_conditions.alpha', 0.05),
            'velocity': {
                'vapor': {
                    'axial': self.get('inlet_conditions.vapor.velocity', 0.1),
                    'lateral': 0.0
                },
                'liquid': {
                    'axial': self.get('inlet_conditions.liquid.velocity', 0.08),
                    'lateral': 0.0
                }
            }
        }
    
    def get_outlet_conditions(self) -> Dict[str, Any]:
        """获取出口条件"""
        return {
            'pressure': self.get('outlet_conditions.pressure', 1.08e5)
        }
    
    def get_physical_parameters(self) -> Dict[str, Any]:
        """获取物理参数"""
        return {
            'gravity': self.get('physical_parameters.gravity', 9.81),
            'turbulent_mixing_coefficient': self.get('physical_parameters.turbulent_mixing_coefficient', 0.005),
            'interfacial_friction_coefficient': self.get('physical_parameters.interfacial_friction_coefficient', 0.5),
            'lateral_flow_resistance': self.get('physical_parameters.lateral_flow_resistance', 0.5)
        }

    def get_fluid_properties(self) -> Dict[str, Any]:
        """获取流体物性参数"""
        return {
            'temperature': self.get('physical_parameters.fluid_properties.temperature', 298.15),
            'liquid_density': self.get('physical_parameters.fluid_properties.liquid_density', 997.0),
            'liquid_viscosity': self.get('physical_parameters.fluid_properties.liquid_viscosity', 8.9e-4),
            'vapor_density': self.get('physical_parameters.fluid_properties.vapor_density', 1.225),
            'vapor_viscosity': self.get('physical_parameters.fluid_properties.vapor_viscosity', 1.81e-5)
        }

    def get_boundary_conditions(self) -> Dict[str, Any]:
        """获取边界条件配置"""
        return self.get('boundary_conditions', {})
    
    def get_time_settings(self) -> Dict[str, Any]:
        """获取时间设置"""
        return {
            'initial_dt': self.get('time_settings.initial_dt', 1e-4),
            'min_dt': self.get('time_settings.min_dt', 1e-6),
            'max_dt': self.get('time_settings.max_dt', 0.01)
        }
    
    def print_config_summary(self):
        """打印配置摘要"""
        logging.info("="*50)
        logging.info("配置参数摘要:")
        logging.info(f"  网格配置: {self.get_grid_config()}")
        logging.info(f"  几何配置: {self.get_geometry_config()}")
        logging.info(f"  求解器配置: {self.get_solver_config()}")
        logging.info(f"  入口条件: {self.get_inlet_conditions()}")
        logging.info(f"  出口条件: {self.get_outlet_conditions()}")
        logging.info(f"  物理参数: {self.get_physical_parameters()}")
        logging.info("="*50)

# 全局配置管理器实例
_config_manager = None

def get_config_manager() -> ConfigManager:
    """获取全局配置管理器实例"""
    global _config_manager
    if _config_manager is None:
        _config_manager = ConfigManager()
    return _config_manager

def reload_config(config_path: Optional[str] = None):
    """重新加载配置"""
    global _config_manager
    _config_manager = ConfigManager(config_path)
    return _config_manager